import subprocess
from datetime import timedelta

from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.utils.translation import gettext_lazy, gettext as _
from django.db.models import Count, Sum, Max

from drf_yasg import openapi
from rest_framework.response import Response
from drf_yasg.utils import swagger_auto_schema, no_body

from ceph.models import GlobalConfig
from utils.view import CustomGenericViewSet
from api import permissions
from api import exceptions
from .views import Bucket, build_harbor_object, RadosError, CephCluster

User = get_user_model()


class BucketResourceViewSet(CustomGenericViewSet):
    """
    存储桶资源统计
    """
    permission_classes = [permissions.IsAuthenticatedOrBucketToken]
    pagination_class = None

    @swagger_auto_schema(
        operation_summary=gettext_lazy('存储桶资源统计'),
        manual_parameters=[
            openapi.Parameter(
                name='unit',
                in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                required=False,
                description='容量计算单位（默认KB，可选GB、TB、PB）'
            )
        ],
        responses={
            200: ""
        }
    )
    def list(self, request, *args, **kwargs):
        """
        存储桶资源统计

            >>Http Code: 状态码200:
                {
                  "code": 200,
                  "code_text": "successful",
                  "stats": {
                    "bucket_count": 2,
                    "bucket_all_size": 12280.0498046875,  # 所有存储桶数据量总和
                    "latest_time": "2024-05-15T07:08:34.784299Z", 最近更新时间
                    "ceph_total": 104853504,   # 所有 ceph 集群总容量
                    "ceph_use": 38178236,   # 所有 ceph 集群使用量
                    "usage_rate": 0.3641102542457713,   # 　ceph 使用率
                    "user_count": 3, # 用户数量
                    "user_active_count": 2 # 用户有效数量
                    "unit": "KB"
                  }
                }
        """

        unit = str.upper(request.query_params.get('unit', 'KB'))
        if unit not in ['GB', 'TB', 'PB', 'KB']:
            exc = exceptions.BadRequest(message='无效的内存单位, 正确格式为KB、GB、TB、PB或为空')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        bucket = Bucket.objects.aggregate(bucket_count=Count('id'), bucket_all_size=Sum('size'),
                                          latest_time=Max('stats_time'))
        bucket['bucket_all_size'] = bucket['bucket_all_size'] / 1024  # bucket_all_size 单位为 byte 修改为 KB

        try:
            ceph_stats = self.get_ceph_stats()
        except exceptions.Error as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        bucket.update(ceph_stats)

        user_qs = User.objects.all()
        user_count = user_qs.count()
        user_active = user_qs.filter(is_active=True).count()
        bucket['user_count'] = user_count
        bucket['user_active_count'] = user_active

        bucket = self.get_unit_stats(unit=unit, bucket=bucket)
        try:
            self.statistics_all_bucket_size(bucket['latest_time'])
        except Exception as exc:
            pass

        return Response({
            'code': 200,
            'code_text': 'successful',
            'stats': bucket,
        })

    def get_unit_stats(self, unit, bucket):
        """
        获取单位统计信息
        """
        dict_unit = {"GB": 2, "TB": 3, "PB": 4, }

        if unit not in dict_unit:
            bucket['usage_rate'] = bucket['ceph_use'] / bucket['ceph_total']
            bucket['unit'] = unit
            return bucket

        multiple = dict_unit[unit]
        bucket['usage_rate'] = bucket['ceph_use'] / bucket['ceph_total']
        bucket['bucket_all_size'] = bucket['bucket_all_size'] / (1024 ** multiple)
        bucket['ceph_total'] = bucket['ceph_total'] / (1024 ** multiple)
        bucket['ceph_use'] = bucket['ceph_use'] / (1024 ** multiple)
        bucket['unit'] = unit

        return bucket

    def get_ceph_stats(self):

        ceph_config = CephCluster.objects.all()

        ceph_stats = {'ceph_total': 0, 'ceph_use': 0}

        for ceph in ceph_config:

            try:
                stats = build_harbor_object(using=str(ceph.id), pool_name='', obj_id='').get_cluster_stats()
            except RadosError as e:
                raise exceptions.BadRequest(message=_('获取ceph集群信息错误') + str(e))

            ceph_stats['ceph_total'] += stats['kb']
            ceph_stats['ceph_use'] += stats['kb_used']

        return ceph_stats

    @staticmethod
    def statistics_all_bucket_size(last_time):
        """执行存储桶大小统计脚本
        :param last_time: datetime
        """

        now_t = timezone.now() - timedelta(minutes=30)
        now_time_timestamp = now_t.timestamp()
        bucket_update_time_timestamp = last_time.timestamp()
        if now_time_timestamp > bucket_update_time_timestamp:
            # 指定脚本文件路径
            command = 'python3 /home/uwsgi/iharbor/scripts/run_update_bucket_size.py >> /var/log/nginx/run_update_bucket_size.log'
            subprocess.Popen(command, shell=True)
        return


class ServiceBasicInfoViewSet(CustomGenericViewSet):
    """
    服务基本信息
    """
    permission_classes = [permissions.IsAuthenticatedOrBucketToken]
    pagination_class = None

    @swagger_auto_schema(
        operation_summary=gettext_lazy('服务基本信息'),
        responses={
            200: ""
        }
    )
    def list(self, request, *args, **kwargs):
        """
        服务基本信息

            >>Http Code: 状态码200:
                {
                  "code": 200,
                  "code_text": "successful",
                  "info": {
                    "service_url": "http://xxx",
                    "api_docs": "http://xxx/apidocs/",
                    "nextcloud_url": "http://xxx"
                    "service_s3_url": "http://xxx"
                    "service_ftp_url": "http://xxx"
                  }
                }

            >>Http Code: 状态码500:
                {
                    "code": 500,
                    "code_text": "无法获基本信息, xxxx"
                }

        """

        s3_host = None
        host = request.get_host()
        http_protocol = request.scheme if request.scheme else 'https'
        if host:
            try:
                s3_server_http_host_name = getattr(settings, 'S3_SERVER_HTTP_HOST_NAME', None)
                host = s3_server_http_host_name[0].replace('s3', '')
                s3_host = s3_server_http_host_name[0]
            except Exception as e:
                exc = exceptions.Error(message=f'无法获基本信息，{str(e)}')
                return Response(data=exc.err_data_old(), status=exc.status_code)

        next_url = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.NEXTCLOUD_SERVICE_URL.value).first()
        if next_url:
            try:
                if ',' in next_url.content:

                    next_url = next_url.content.split(',')[0]
                else:
                    next_url = GlobalConfig.parse_lines(text=next_url.content)[0]
            except Exception as e:
                next_url = ''
        else:
            next_url = ''

        ftp_url = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.FTP_DOMAIN_NAME.value).first()
        if ftp_url:
            try:
                ftp_url = GlobalConfig.parse_lines(text=ftp_url.content)[0]
            except Exception as e:
                ftp_url = ''
        else:
            ftp_url = ''

        return Response({
            'code': 200,
            'code_text': 'successful',
            'info': {'service_url': f'{http_protocol}://{host}', 'api_docs': f'{http_protocol}://{host}/apidocs/',
                     'nextcloud_url':f'{http_protocol}://{next_url}', 'service_s3_url': f'{http_protocol}://{s3_host}',
                     'service_ftp_url': f'{http_protocol}://{ftp_url}'},
        })
